package com.hustbaidu.hustmap;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.R.integer;
import android.content.Context;
import android.content.IntentFilter;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.TextView;

public class HustMapView extends ViewGroup{
	private MapView mv;
	private MapBackgroundView mbgv;
	private InfoWindowView iwv;
	private InfoWindowSurfaceView iwsv;
	private PlaceLabelView plView;
	private GestureDetector mapGestureDetector;
	private MapConfFromXml mapConf;
	
	private boolean pathFlag;
	
	
	public HustMapView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public HustMapView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public HustMapView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		this.setLongClickable(true);
		init(context);
		initChild(context);
		mapGestureDetector = new GestureDetector(new MapGestureListener());
		
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		mapGestureDetector.onTouchEvent(ev);
		return false;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		System.out.println("mapview onTouchEvent");
		return super.onTouchEvent(event);
//		return true;
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub		
		View child = getChildAt(0);
		child.setVisibility(View.VISIBLE);
		child.measure(r - l, b - t);
		child.layout(0, 0, child.getMeasuredWidth(), child .getMeasuredHeight());

		child = getChildAt(1);
//		child.setVisibility(View.INVISIBLE);
		child.measure(r - l, b - t);
//		System.out.println("test:" + child.getMeasuredWidth() + " : " + child .getMeasuredHeight());
//		System.out.println(plView.getOffsetX() + " : " + plView.getOffsetY());
		child.layout(plView.getOffsetX(), plView.getOffsetY(), child.getMeasuredWidth() + plView.getOffsetX(), child.getMeasuredHeight() + plView.getOffsetY());
//		child.layout(0, 0, r - l, b - t);
		
//		child = getChildAt(2);
		
		if(pathFlag){
			List<PathSegmentView> pathList = PathManager.getPathList();
			PathSegmentView psView = null;
	//		System.out.println("2 size : " + pathList.size());
			for(int i = 0; i < pathList.size(); i++){
				psView = pathList.get(i);
				psView.measure(r - l, b - t);
				psView.layout(psView.getOffsetX(), psView.getOffsetY(), 
						psView.getOffsetX() + psView.getMeasuredWidth(), 
						psView.getOffsetY() + psView.getMeasuredHeight());
			}
			
			PathPointView ppView = PathManager.getStartPointView();
			ppView.measure(r - l, b - t);
			ppView.layout(ppView.getOffsetX(), ppView.getOffsetY(), 
					ppView.getOffsetX() + ppView.getMeasuredWidth(), 
					ppView.getOffsetY() + ppView.getMeasuredHeight());
	//		System.out.println("1 : " + ppView.getOffsetX() + " : " + ppView.getOffsetY() + " : " + ppView.getMeasuredWidth() + " : " + ppView.getMeasuredHeight());
			
			ppView = PathManager.getEndPointView();
			ppView.measure(r - l, b - t);
			ppView.layout(ppView.getOffsetX(), ppView.getOffsetY(), 
					ppView.getOffsetX() + ppView.getMeasuredWidth(), 
					ppView.getOffsetY() + ppView.getMeasuredHeight());
	//		System.out.println("2 : " + ppView.getOffsetX() + " : " + ppView.getOffsetY() + " : " + ppView.getMeasuredWidth() + " : " + ppView.getMeasuredHeight());
		}
		
	}
	
	private void init(Context context){
		PathManager.setContext(context);
		mbgv = new MapBackgroundView(context, this);
		
		plView = new PlaceLabelView(context, "南一楼");
		
		mapConf = new MapConfFromXml();
		mapConf.mapInit("/sdcard/HustMapData");
	}
	
	private void initChild(Context context){
		
		this.addView(mbgv);	
		this.addView(plView);
		
//		PathManager.generatePath(0, 0, 0, 0, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
//		List<PathSegmentView> pathList = PathManager.getPathList();
////		System.out.println("1 size : " + pathList.size());
//		for(int i = 0; i < pathList.size(); i++){	
//			this.addView(pathList.get(i));
//		}
//		this.addView(PathManager.getStartPointView());
//		this.addView(PathManager.getEndPointView());
		
	}
	
	public void choosePlace(String name){
		PlaceInfo place = PlaceManager.getPlaceByName(name);
		if(place != null){
			mbgv.choosePlace(place);
			mbgv.invalidate();
			PlaceType type = PlaceManager.getTypeByPlace(place);
			plView.setPlace(place, type);
			plView.moveTo(mbgv.placeOffsetX - plView.getMeasuredWidth() / 2, mbgv.placeOffsetY - plView.getMeasuredHeight());
			plView.requestLayout();
			plView.setVisibility(View.VISIBLE);
		}
	}
	
	public void searchPath(String startName, String stopName){
		//TODO
		clearPath();
//		PlaceInfo startPlace = PlaceManager.getPlaceByName(startName);
//		PlaceInfo stopPlace = PlaceManager.getPlaceByName(stopName);
		if(startName.equals("南一楼") && stopName.equals("东八楼")){
			PathManager.generatePath(5, 13, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
		else if(startName.equals("南大门") && stopName.equals("东八楼")){
			PathManager.generatePath(0, 13, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
		else if(startName.equals("南大门") && stopName.equals("南一楼")){
			PathManager.generatePath(0, 2, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
		else if(startName.equals("南一楼") && stopName.equals("南大门")){
			PathManager.generatePath(2, 0, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
		else if(startName.equals("东八楼") && stopName.equals("南大门")){
			PathManager.generatePath(13, 0, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
		else if(startName.equals("东八楼") && stopName.equals("南一楼")){
			PathManager.generatePath(13, 5, mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		}
//		PathManager.generatePath(Integer.valueOf(startName), Integer.valueOf(stopName), mbgv.getCurrentChipX(), mbgv.getCurrentChipY(), mbgv.getOffsetX(), mbgv.getOffsetY(), mbgv.getMapChipWidth(), mbgv.getMapChipHeight());
		List<PathSegmentView> pathList = PathManager.getPathList();
//		System.out.println("1 size : " + pathList.size());
		for(int i = 0; i < pathList.size(); i++){	
			this.addView(pathList.get(i));
		}
		this.addView(PathManager.getStartPointView());
		this.addView(PathManager.getEndPointView());
		pathFlag = true;
		this.requestLayout();
	}
	
	private void clearPath(){
		List<PathSegmentView> psList = PathManager.getPathList();
		for(int i = 0; i < psList.size(); i++){
			this.removeView(psList.get(i));
		}
		this.removeView(PathManager.getStartPointView());
		this.removeView(PathManager.getEndPointView());
		pathFlag = false;
	}
	
	public void touchOnPlace(int realTouchX, int realTouchY){
		PlaceInfo place = PlaceManager.getPlaceByTouchPosition(realTouchX, realTouchY);		
		if(place != null){
			PlaceType type = PlaceManager.getTypeByPlace(place);
			plView.setPlace(place, type);
			plView.moveTo( place.getPlacePositionX() - mbgv.getCurrentChipX() * mbgv.getMapChipWidth() - mbgv.getOffsetX() - plView.getMeasuredWidth() / 2, 
					place.getPlacePositionY() - mbgv.getCurrentChipY() * mbgv.getMapChipHeight() - mbgv.getOffsetY() - plView.getMeasuredHeight());
			plView.requestLayout();
			plView.setVisibility(View.VISIBLE);
		}
		else{
			plView.setVisibility(View.GONE);
		}
		
	}

	private class MapGestureListener extends SimpleOnGestureListener{
		
		@Override
		public boolean onSingleTapConfirmed(MotionEvent e) {
			// TODO Auto-generated method stub
//			System.out.println("onSingleTapConfirmed");
//			System.out.println(e.getX() + " : " + e.getY());
			return super.onSingleTapConfirmed(e);
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
//			System.out.println("onSingleTapUp");
			return super.onSingleTapUp(e);
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			// TODO Auto-generated method stub
			
			mbgv.moveBy((int)distanceX, (int)distanceY);
			mbgv.invalidate();
			plView.move(mbgv.realDistanceX, mbgv.realDistanceY);
			plView.requestLayout();
			if(pathFlag){
				PathManager.move(mbgv.realDistanceX, mbgv.realDistanceY);	
			}
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		@Override
		public boolean onDoubleTap(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onDoubleTap(e);
		}

		@Override
		public boolean onDoubleTapEvent(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onDoubleTapEvent(e);
		}

		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
//			System.out.println("onDown");
//			System.out.println(super.onDown(e));
			return super.onDown(e);
//			return false;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			// TODO Auto-generated method stub
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// TODO Auto-generated method stub
			super.onLongPress(e);
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub
			super.onShowPress(e);
		}
		
	}

	/**
	 * 对整个地图进行初始化的类
	 * */
	private class MapConfFromXml{
		private SAXParser parser;
		private String dataPath;
		private String backgroundConfPath;
		private String placeTypeConfPath;
		private String placeConfPath;
		private String nodeConfPath;
		
		/**
		 * 从xml文件获取信息，进行地图初始化
		 * @param dataPath 地图数据包的绝对路径
		 * */
		public void mapInit(String dataPath){
			this.dataPath = dataPath;
			
			SAXParserFactory factory = SAXParserFactory.newInstance();
			File file = null;
	        Reader reader = null;
	        StringBuffer sb = null;
	        int tempchar;
	        
			try {
//				System.out.println("start parser");
				this.parser = factory.newSAXParser();
				
				/*读取地图的全局配置信息，进行初始化*/
				file = new File(dataPath + "/MapConf/map_conf.xml");
				reader = new InputStreamReader(new FileInputStream(file));
				sb = new StringBuffer();	            
	            while ((tempchar = reader.read()) != -1) {
	                    sb.append((char)tempchar);
	            }
	            reader.close();
				parser.parse(new InputSource(new StringReader(sb.toString())), new MapSAXHandler());
				
				/*读取地图背景主图的配置信息，进行背景主图的初始化*/
				file = new File(dataPath + backgroundConfPath);
				reader = new InputStreamReader(new FileInputStream(file));
				sb = new StringBuffer();
				while ((tempchar = reader.read()) != -1) {
                    sb.append((char)tempchar);
				}
				reader.close();
				parser.parse(new InputSource(new StringReader(sb.toString())), new BackgroundSAXHandler());
				
				/*读取地点类型的配置信息，进行地点类型的初始化*/
				file = new File(dataPath + placeTypeConfPath);
				reader = new InputStreamReader(new FileInputStream(file));
				sb = new StringBuffer();
				while ((tempchar = reader.read()) != -1) {
                    sb.append((char)tempchar);
				}
				reader.close();
				parser.parse(new InputSource(new StringReader(sb.toString())), new PlaceTypeSAXHandler());
				
				/*读取地点的配置信息，进行地点的初始化*/
				file = new File(dataPath + placeConfPath);
				reader = new InputStreamReader(new FileInputStream(file));
				sb = new StringBuffer();
				while ((tempchar = reader.read()) != -1) {
                    sb.append((char)tempchar);
				}
				reader.close();
				parser.parse(new InputSource(new StringReader(sb.toString())), new PlaceSAXHandler());
				
				/*读取节点的配置信息，进行节点的初始化*/
				file = new File(dataPath + nodeConfPath);
				reader = new InputStreamReader(new FileInputStream(file));
				sb = new StringBuffer();
				while ((tempchar = reader.read()) != -1) {
                    sb.append((char)tempchar);
				}
				reader.close();
				parser.parse(new InputSource(new StringReader(sb.toString())), new NodeSAXHandler());
				
//				System.out.println("end parser");
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		
		private class MapSAXHandler extends DefaultHandler{
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				// TODO Auto-generated method stub
				if(qName.equals("background_conf_path")){
					backgroundConfPath = attributes.getValue("value");
				}
				else if(qName.equals("place_type_conf_path")){
					placeTypeConfPath = attributes.getValue("value");
				}
				else if(qName.equals("place_conf_path")){
					placeConfPath = attributes.getValue("value");
				}
				else if(qName.equals("node_conf_path")){
					nodeConfPath = attributes.getValue("value");
				}
				
			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}
			
		}
		
		private class BackgroundSAXHandler extends DefaultHandler{
			private String imgPath;
			private String imgPrefix;
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				// TODO Auto-generated method stub
				if(qName.equals("background_basic_param")){
					imgPath = attributes.getValue("img_path");
					imgPrefix = attributes.getValue("img_prefix");
					mbgv.setMapChipWidth(Integer.parseInt(attributes.getValue("chip_width")));
					mbgv.setMapChipHeight(Integer.parseInt(attributes.getValue("chip_height")));
					mbgv.setMapChipTotalX(Integer.parseInt(attributes.getValue("chip_total_x")));
					mbgv.setMapChipTotalY(Integer.parseInt(attributes.getValue("chip_total_y")));
					mbgv.setChipImgPath(dataPath + imgPath);
					mbgv.initMapChip(imgPrefix);
				}

			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}
		}

		private class PlaceTypeSAXHandler extends DefaultHandler{
			private PlaceType placeType;
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				// TODO Auto-generated method stub
				if(qName.equals("place_type")){
					placeType = new PlaceType();
					placeType.setTypeId(Integer.valueOf(attributes.getValue("id")));
					placeType.setTypeName(attributes.getValue("name"));
					placeType.setTypeImg(attributes.getValue("img"));
					PlaceManager.addPlaceType(placeType);
				}

			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}
		}
		
		private class PlaceSAXHandler extends DefaultHandler{
			private PlaceInfo placeInfo;
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				// TODO Auto-generated method stub
				if(qName.equals("place")){
					placeInfo = new PlaceInfo();
					
					placeInfo.setId(Integer.valueOf(attributes.getValue("id")));
					placeInfo.setPlaceName(attributes.getValue("name"));
					placeInfo.setPlaceImg(dataPath + attributes.getValue("img"));
					
					String[] position = attributes.getValue("position").split(";");
					placeInfo.setPlacePositionX(Integer.valueOf(position[0]));
					placeInfo.setPlacePositionY(Integer.valueOf(position[1]));
					
					String[] touch = attributes.getValue("touch").split(";");
					placeInfo.setTouchLeft(Integer.valueOf(touch[0]));
					placeInfo.setTouchTop(Integer.valueOf(touch[1]));
					placeInfo.setTouchRight(Integer.valueOf(touch[2]));
					placeInfo.setTouchBottom(Integer.valueOf(touch[3]));
					
					placeInfo.setPlaceType(Integer.valueOf(attributes.getValue("type")));
					placeInfo.setPlaceRoad(Integer.valueOf(attributes.getValue("road")));
					placeInfo.setPlaceIntroduce(attributes.getValue("introduce"));
					
					PlaceManager.addPlaceInfo(placeInfo);
				}

			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}
		}
		
		private class NodeSAXHandler extends DefaultHandler{
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				// TODO Auto-generated method stub
				if(qName.equals("node")){
					NodeInfo nodeInfo = new NodeInfo();
					nodeInfo.setId(Integer.valueOf(attributes.getValue("id")));
					String[] s = attributes.getValue("position").split(";");
					nodeInfo.setNodePositionX(Integer.valueOf(s[0]));
					nodeInfo.setNodePositionY(Integer.valueOf(s[1]));
					s = attributes.getValue("linked_node").split(";");
					NodeLinkedInfo nodeLinkedInfo = null;
					String[] str = null;
					for(int i = 0; i < s.length; i++){
						nodeLinkedInfo = new NodeLinkedInfo();
						str = s[i].split(":");
						nodeLinkedInfo.setId(Integer.valueOf(str[0]));
						nodeLinkedInfo.setDistance(Integer.valueOf(str[1]));
						nodeInfo.getNodeLinkedList().add(nodeLinkedInfo);
					}
					PathManager.addNode(nodeInfo);
				}
				
				
			}

			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				// TODO Auto-generated method stub
				
			}
			
		}
		
		
		
		
	}

	
	
	interface OnPlaceLabelLongPressListener{
		public void onLongPress(PlaceInfo place, PlaceType type);
	}
	
	public void setOnPlaceLabelLongPressListener(OnPlaceLabelLongPressListener listener){
		plView.setOnPlaceLabelLongPressListener(listener);
	}
	
	interface OnPlaceLabelClickListener{
		public void onClick(PlaceInfo place, PlaceType type);
	}
	
	public void setOnPlaceLabelClickListener(OnPlaceLabelClickListener listener){
		plView.setOnPlaceLabelClickListener(listener);
	}
}
